package at.theengine.android.botstorage;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import at.theengine.android.botstorage.gsobjects.Bucket;
import at.theengine.android.botstorage.gsobjects.File;
import at.theengine.android.botstorage.gsobjects.Folder;
import at.theengine.android.botstorage.gsobjects.GsObject;
import at.theengine.android.botstorage.gsobjects.GsObjects;
import at.theengine.android.botstorage.gsobjects.GsObject.ObjectType;

public class GsObjectBuilder {

	public static Bucket[] buildBucketObjects(String xmlBuckets) throws SAXException, IOException, ParserConfigurationException, BotStorageException{
		Document dom = buildDocument(xmlBuckets);
		
		//check if this xml response is a error response
		checkForError(dom);
		
		//Get buckets as Nodes
		NodeList buckets = dom.getElementsByTagName("Bucket");
		 
		//prepare Array
		Bucket[] bucketObjects = new Bucket[buckets.getLength()];
		
		//get Owner Data
		String ownerId = "";
		String ownerDisplayName = "";
        NodeList ownerData = dom.getElementsByTagName("Owner").item(0).getChildNodes();
        
        for(int i = 0; i < ownerData.getLength();i++){
        	Node node = ownerData.item(i);
        	if(node.getNodeName().equals("ID")){
        		ownerId = node.getChildNodes().item(0).getNodeValue();
        	} else if(node.getNodeName().equals("DisplayName")){
        		ownerDisplayName = node.getChildNodes().item(0).getNodeValue();
        	}
        }
        
        //generate Bucket Objects
        String name = "";
        String creationDate = "";
        for(int i = 0; i < buckets.getLength();i++){
        	Node bucket = buckets.item(i);
        	for(int j = 0; j < bucket.getChildNodes().getLength();j++){
        		Node node = bucket.getChildNodes().item(j);
	        	if(node.getNodeName().equals("Name")){
	        		name = node.getChildNodes().item(0).getNodeValue();
	        	} else if(node.getNodeName().equals("CreationDate")){
	        		creationDate = node.getChildNodes().item(0).getNodeValue();
	        	}
        	}
        	bucketObjects[i] = new Bucket(name,creationDate,ownerId,ownerDisplayName);
        }
		
        return bucketObjects;
	}
	
	public static GsObjects buildGsObjects(String xmlGsObjects) throws SAXException, IOException, ParserConfigurationException, BotStorageException{
		Document dom = buildDocument(xmlGsObjects);
		
		//check if this xml response is a error response
		checkForError(dom);
		
		//Get files as Nodes
		NodeList contents = dom.getElementsByTagName("Contents");
		
		//prepare Temp Array
		GsObjects gsObjects = new GsObjects();
		
        //generate GsObjects
		String key = "";
		String lastModified = "";
		String eTag = "";
		int size = 0;
		String storageClass = "";
		String ownerId = "";
		String ownerDisplayName = "";
		
		try{
	        for(int i = 0; i < contents.getLength();i++){
	        	Node object = contents.item(i);
	        	for(int j = 0; j < object.getChildNodes().getLength();j++){
	        		Node node = object.getChildNodes().item(j);
		        	if(node.getNodeName().equals("Key")){
		        		key = node.getChildNodes().item(0).getNodeValue();
		        	} else if(node.getNodeName().equals("LastModified")){
		        		lastModified = node.getChildNodes().item(0).getNodeValue();
		        	} else if(node.getNodeName().equals("ETag")){
		        		eTag = node.getChildNodes().item(0).getNodeValue();
		        	} else if(node.getNodeName().equals("Size")){
		        		size = Integer.parseInt(node.getChildNodes().item(0).getNodeValue());
		        	} else if(node.getNodeName().equals("StorageClass")){
		        		storageClass = node.getChildNodes().item(0).getNodeValue();
		        	} else if(node.getNodeName().equals("Owner")){
		        		NodeList ownerData = object.getChildNodes();
		        		for(int k = 0; k < object.getChildNodes().getLength();k++){
		        			Node ownerNode = object.getChildNodes().item(k);
		        			if(ownerNode.getNodeName().equals("ID")){
		    	        		ownerId = ownerNode.getChildNodes().item(0).getNodeValue();
		    	        	} else if(ownerNode.getNodeName().equals("DisplayName")){
		    	        		ownerDisplayName = ownerNode.getChildNodes().item(0).getNodeValue();
		    	        	}
		        		}
		        	}
	        	}
	        	
	        	if(!key.endsWith("_$folder$")){
	        		gsObjects.addFile(new File(key,lastModified,eTag,size,storageClass,ownerId,ownerDisplayName));
	        	}
	        }
		} catch(Exception ex){
			//no files for this path
		}
        
		try{
			//Get prefixes as Nodes
			NodeList commonPrefixes = dom.getElementsByTagName("CommonPrefixes");
			
			if(commonPrefixes != null){
				Node prefixes = commonPrefixes.item(0);
				for(int j = 0; j < prefixes.getChildNodes().getLength();j++){
	        		Node node = prefixes.getChildNodes().item(j);
		        	key = node.getChildNodes().item(0).getNodeValue();
		        	gsObjects.addFolder(new Folder(key,"","",-1,"",ownerId,ownerDisplayName));
		        }
			}  
		} catch(Exception ex){
			//no folders
		}
		
        return gsObjects;
	}
	
	private static void checkForError(Document dom) throws BotStorageException{
		//Check for Error Node
		NodeList errors = dom.getElementsByTagName("Error");
		 
		//prepare Array
		if(errors.getLength() == 0){
			return; //no error
		} else {
			Node error = errors.item(0);
			
			String code = "";
			String msg = "";
			
			for(int j = 0; j < error.getChildNodes().getLength();j++){
        		Node node = error.getChildNodes().item(j);
	        	if(node.getNodeName().equals("Code")){
	        		code = node.getChildNodes().item(0).getNodeValue();
	        	} else if(node.getNodeName().equals("Message")){
	        		msg = node.getChildNodes().item(0).getNodeValue();
	        	}
        	}
			
			throw new BotStorageException(code + ": " + msg);
		}
	}
	
	private static Document buildDocument(String xml) throws SAXException, IOException, ParserConfigurationException{
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        ByteArrayInputStream xmlStream = new ByteArrayInputStream(xml.getBytes());
        return db.parse(new InputSource(xmlStream));
	}
	
	
}
